//============================================================================
// Name        : tp2_p2.cpp
// Author      : Andrey Bicalho Santos and Clayson Sandro Celes
// Version     :
// Copyright   : Your copyright notice
// Description : tp2 p2 compnat in C++, Ansi-style
//============================================================================

#include "ant_clustering_problem.h"

using namespace std;


//-------------------------------------------------------------------------------------
int main(int argc, char** argv) {

	string path_file;
	Dimension dim_data;

	int grid_size = 0,num_formigas = 0, neighborhood_size = 0, refresh_time = 1, aumento_display = 1, distance_type = 1;
	double constante_k1 = 0.00, constante_k2 = 0.00, alfa = 0.5;
	Point dim_grid;
	if(argc < 2){
		cout << "Insira o dataset: " << endl; cin >> path_file;
		cout << "Insira o tamanho da Grid: " << endl; cin >> grid_size;
		cout << "Insira o numero de formigas: " << endl; cin >> num_formigas;
		cout << "Insira o tamanho da vizinhanca das formigas: " << endl; cin >> neighborhood_size;
		cout << "Insira a constante k1: " << endl; cin >> constante_k1;
		cout << "Insira a constante k2: " << endl; cin >> constante_k2;
		cout << "Insira Alfa: " << endl; cin >> alfa;
		cout << "Insira o tipo de metrica de Similaridade: (0 - Euclidiana      1 - Coseno)" << endl; cin >> distance_type;
		cout << "Insira o Tempo de Atualizacao do Display (ms): " << endl; cin >> refresh_time;
		cout << "Insira o valor de aumento do display (0 - nao muda)" << endl; cin >> aumento_display;

	}
	else{
		path_file = argv[1];
		grid_size = atoi(argv[2]);
		num_formigas = atoi(argv[3]);
		neighborhood_size = atoi(argv[4]);
		constante_k1 = atof(argv[5]);
		constante_k2 = atof(argv[6]);
		alfa = atof(argv[7]);
		distance_type = atoi(argv[8]);
		refresh_time = atoi(argv[9]);
		aumento_display = atoi(argv[10]);

	}

	dim_grid.x = dim_grid.y = grid_size;
	cout << path_file<< endl;
	double **data = load_fileToArray(path_file.c_str(), &dim_data);
	int num_amostras = dim_data.x;

	//printData(data,dim_data.x,dim_data.y);
	//pera("dataset");

	//building grid and workspace
	//grid - transformed data space
	//workspace - share place ants can walk through
	int **grid,**workspace;
	grid = build_matrix(dim_grid);
	workspace = copy_matrix(grid,dim_grid);

	CImg<int> cimg_grid_workspace(dim_grid.x,dim_grid.y,1,3);
	CImgDisplay main_disp(cimg_grid_workspace,"Grid/Workspace - ACC",0);
	int aumento_x = 1,aumento_y = 1,fator_de_aumento = aumento_display;
		if(aumento_display > 0){
				aumento_x = dim_grid.x * fator_de_aumento;
				aumento_y = dim_grid.y * fator_de_aumento;
				main_disp.resize(aumento_x,aumento_y);
		}


	// criando os dados
	Data *nDspace;
	nDspace = load_data(data,dim_data);
	transform_to_grid(dim_grid,nDspace,num_amostras,neighborhood_size);

	//print_grid_workspace(grid,dim_grid);
	//pera("grid");


	// criando formigas
	double max_euclidian_distance = get_max_euclidian_distance(nDspace,num_amostras);
	//cout << "\n" << max_euclidian_distance << "\n";
	//pera("max dist");
	AntClustering *formigas;
	formigas = new AntClustering[num_formigas];
	Point nest; nest.x = nest.y = grid_size/2;
	Behavior b; b.searching = false;
	for(int i=0;i<num_formigas;i++){
		formigas[i].set_ID(i);
		formigas[i].set_neighborhood_size(neighborhood_size);
		formigas[i].initialize_neighborhood();
		formigas[i].set_position(nest);
		formigas[i].set_constant_k1_k2(constante_k1,constante_k2);
		formigas[i].max_distancia_euclidiana = max_euclidian_distance;
		formigas[i].set_alfa(alfa);
		if(distance_type != 0)
			formigas[i].distance_type = true;
		else formigas[i].distance_type = false;
	}
	set_workspace_ant_position(formigas,num_formigas,dim_grid,neighborhood_size);

	initialize_grid_workspace(grid,workspace,dim_grid,nDspace,num_amostras,formigas,num_formigas);


	int it = 0;
	double *intra, avg_intra = 0,inter = 0, cvbeta = 0;
	int num_clusters = count_num_clusters(nDspace,num_amostras);
	intra = new double[num_clusters];
	//laco principal
	while(!main_disp.is_closed()){

		for(int i=0;i<num_formigas;i++)
			formigas[i].Walk(grid,workspace,dim_grid,nDspace,num_amostras);


		//calculando estatisticas...
		if(main_disp.is_keyF1()){
			avg_intra = 0.000000000;
			for(int i=0;i<num_clusters;i++){
				intra[i] = d_intra(nDspace,num_amostras,i);
				avg_intra += intra[i];
			}

			avg_intra = avg_intra/(double)num_clusters;
			inter = d_inter(nDspace,num_amostras);
			cvbeta = avg_intra/inter;
			printf("\nEstatisticas da iteracao: %d\n",it);
			for(int i=0;i<num_clusters;i++)
				printf("\nDistancia Intra-Cluster do cluster %d = %f",i,intra[i]);

			printf("\n\nDistancia Intra-Cluster media = %f \nDistancia Inter-Cluster media = %f\nCVBeta = %f\n\n",avg_intra,inter,cvbeta);
		}



		cimg_grid_workspace = update_display(nDspace,num_amostras,grid,workspace,dim_grid,cimg_grid_workspace);


		cimg_grid_workspace.display(main_disp);
		main_disp.wait(refresh_time);
		it++;
	}






	//liberando memoria
	destroy_matrix(grid,dim_grid);
	destroy_matrix(workspace,dim_grid);
	cout << "\nit works!\n";
	return 0;
}
//-------------------------------------------------------------------------------------

